﻿Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.Marshal
'Imports nsShellZipper.Shell32
Imports nsShellZipper.Shell32ZipOnly

Public Class ShellZipper : Implements IDisposable

    Private _shell As Shell32.IShellDispatch

    Public Sub Zip(ByVal folderName As String, _
                   Optional ByVal zipFileName As String = Nothing)

        folderName = Path.GetFullPath(folderName)
        If zipFileName Is Nothing Then
            zipFileName = folderName & ".zip"
        Else
            zipFileName = Path.GetFullPath(zipFileName)
        End If
        If File.Exists(zipFileName) Then File.Delete(zipFileName)
        'leeres ZipFile erzeugen
        Dim emptyZipData = New Byte() {80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, _
                                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
        Using fs = New FileStream(zipFileName, FileMode.CreateNew)
            fs.Write(emptyZipData, 0, emptyZipData.Length)
        End Using
        ShellCopy(folderName, zipFileName)
    End Sub

    Public Sub UnZip(ByVal zipFileName As String, _
                     Optional ByVal folderName As String = Nothing)
        zipFileName = Path.GetFullPath(zipFileName)
        If folderName Is Nothing Then
            Dim i = zipFileName.LastIndexOf("."c)
            folderName = zipFileName.Substring(0, i)
        Else
            folderName = Path.GetFullPath(folderName)
        End If
        If Directory.Exists(folderName) Then Directory.Delete(folderName, True)
        Directory.CreateDirectory(folderName)
        ShellCopy(zipFileName, folderName)
    End Sub

    Private Sub ShellCopy(ByVal source As String, ByVal destination As String)
        ' Für die Shell sind Zip-Dateien einfach Datei-Ordner. Zippen/UnZippen 
        '  ist also ein simpler Kopier-Vorgang von einen in den 
        '  anderen ShellFolder
        If _shell Is Nothing Then _shell = _
            DirectCast(CreateObject("Shell.Application"), IShellDispatch)
        Dim dst = _shell.NameSpace(destination)
        Dim src = _shell.NameSpace(source)
        Dim itms = src.Items
        dst.CopyHere(itms)
        ' COM-Objekte sind speziell aufzuräumen - beachte auch die Reihenfolge
        FinalReleaseComObject(itms)
        FinalReleaseComObject(src)
        FinalReleaseComObject(dst)
    End Sub


#Region "IDisposable"

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If _shell Is Nothing Then Return
        FinalReleaseComObject(_shell)
        _shell = Nothing
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

#End Region 'IDisposable

End Class
